<template>
	<div class="container" :style="{ ...container }">
		<div
			class="title-container"
			v-if="props.config.style.titleShow"
			:style="{ justifyContent: props.config.style.align }"
		>
			<div class="flex items-center">
				<i
					:class="['iconfont', props.config.style.titleIcon]"
					:style="{ ...titleIconStyle }"
					v-if="props.config.style.titleIconShow"
				></i>
				<span class="font-7" :style="{ ...titleStyle }">{{ props.config.style.title }}</span>
			</div>
			<div class="flex items-center" v-if="props.config.style.titleEndShow">
				<span class="font-7" :style="{ ...titleEndStyle }">{{ props.config.style.titleEnd }}</span>
				<i
					:class="['iconfont', props.config.style.titleEndIcon]"
					:style="{ ...titleEndIconStyle }"
					v-if="props.config.style.titleEndIconShow"
				></i>
			</div>
		</div>
		<div ref="chartContainer" class="chart-container"></div>
	</div>
</template>

<script setup>
	import config from './config'
	import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
	import { Pie } from '@antv/g2plot'
	import datasetApi from '@/views/plugin/dashboard/api/datasetApi'
	import { designStore } from '@/views/plugin/dashboard/store'
	import { observeChartResize, updateChart, cleanupChart } from '@/views/plugin/dashboard/plugin/utils/chartUtils'

	const useDesignStore = designStore()
	const props = defineProps({
		config: {
			type: Object,
			default: () => config
		},
		previewConfig: {
			type: Object,
			default: () => config
		}
	})

	const chartContainer = ref(null)
	const chartInstance = ref(null)
	const resizeObserver = ref(null)
	// 数据源数据
	const chartData = ref(props.config.data.chartData.value)
	// 旧的dataSetJson 用于比较是否一样就不重新获取数据
	const oldDataSetJson = ref(props.config.dataSetConfig.dataSetJson)
	// 图表配置
	const chartOptions = ref({})

	// 获取数据源数据函数
	const fetchChartData = async (isFlag = false) => {
		const { dataSetType, dataSetJson } = props.config.dataSetConfig
		chartData.value = props.config.data.chartData.value || []
		// 如果是静态数据
		if (dataSetType === 0) return

		const isNew = isFlag || JSON.stringify(oldDataSetJson.value) !== JSON.stringify(dataSetJson)
		// 如果是数据源且有效
		if (dataSetType === 1 && dataSetJson && Object.keys(dataSetJson).length > 0 && isNew) {
			// 更新值
			oldDataSetJson.value = dataSetJson
			try {
				// 获取数据源数据
				const res = await datasetApi.preview(dataSetJson)

				// 确保有数据返回
				if (res && res.length > 0) {
					const angleField = props.config.data.angleField.field
					const colorField = props.config.data.colorField.field

					// 确保选择了有效的字段
					if (angleField && colorField) {
						// 检查返回的数据中是否包含所选字段
						const firstItem = res[0]
						if (firstItem && angleField in firstItem && colorField in firstItem) {
							chartData.value = res
						} else {
							console.error('数据源中不包含所选字段:', {
								angleField,
								colorField,
								availableFields: Object.keys(firstItem || {})
							})
							chartData.value = []
						}
					} else {
						console.error('未选择有效的字段:', { angleField, colorField })
						chartData.value = []
					}
				} else {
					chartData.value = []
				}
			} catch (error) {
				console.error('获取数据源数据失败:', error)
				chartData.value = []
			}
		}
	}

	// 初始化图表配置
	const setChartOptions = () => {
		// 获取当前数据
		const currentData = chartData.value || []
		const angleField = props.config.data.angleField.field
		const colorField = props.config.data.colorField.field

		// 计算总和用于中心统计文本
		const totalValue = currentData.reduce((sum, item) => sum + (Number(item[angleField]) || 0), 0)

		chartOptions.value = {
			appendPadding: 10,
			data: currentData,
			angleField,
			colorField,
			radius: props.config.style.radius,
			color: props.config.style.chartColor,
			// 标签配置
			label: props.config.style.showLabel
				? {
						type: props.config.style.labelType,
						labelHeight: 28,
						content: '{name}: {percentage}',
						style: {
							textAlign: 'center',
							fontSize: 12
						}
					}
				: false,
			// 图例配置
			legend: props.config.style.showLegend
				? {
						position: props.config.style.legendPosition
					}
				: false,
			// 中心统计文本配置
			statistic: props.config.style.showStatistic
				? {
						title: {
							style: {
								whiteSpace: 'pre-wrap',
								overflow: 'hidden',
								textOverflow: 'ellipsis',
								fontSize: '14px',
								color: '#4B535E'
							},
							content: props.config.style.statisticTitle
						},
						content: {
							style: {
								whiteSpace: 'pre-wrap',
								overflow: 'hidden',
								textOverflow: 'ellipsis',
								fontSize: '20px',
								color: '#4B535E'
							},
							content: totalValue.toString()
						}
					}
				: false,
			interactions: [{ type: 'element-active' }, { type: 'element-selected' }]
		}
	}
	// 初始化图表
	const initChart = async () => {
		await nextTick()
		if (chartContainer.value && !chartInstance.value) {
			chartInstance.value = new Pie(chartContainer.value, chartOptions.value)
			chartInstance.value.render()
		}
	}

	// 暴露给外部的更新配置方法
	const onReload = async (isFlag = false) => {
		// 获取数据
		await fetchChartData(isFlag)
		// 初始化图表配置
		setChartOptions()

		// 更新图表
		if (chartInstance.value) {
			await nextTick(() => {
				updateChart(chartInstance.value, chartOptions.value)
			})
		} else {
			await initChart()
		}
	}

	// 组件挂载
	onMounted(async () => {
		// 初始化图表
		await onReload()

		// 监听容器尺寸变化，使外层卡片拖动时图表能更新
		if (chartContainer.value) {
			resizeObserver.value = observeChartResize(chartContainer.value, chartInstance.value, resizeObserver.value)
		}
	})

	// 暴露方法给父组件
	defineExpose({
		onReload
	})

	// 组件卸载前清理
	onBeforeUnmount(() => {
		// 使用通用方法清理图表资源
		cleanupChart(chartInstance.value, resizeObserver.value)
	})

	// 样式计算
	const container = computed(() => ({
		backgroundColor: props.config.style.bgColor,
		backgroundImage: props.config.style.bgImg ? `url(${props.config.style.bgImg})` : 'none',
		borderStyle: props.config.style.borderStyle,
		borderColor: props.config.style.borderColor,
		borderWidth: props.config.style.borderWidth + 'px',
		paddingTop: props.config.style.paddingT + 'px',
		paddingRight: props.config.style.paddingR + 'px',
		paddingBottom: props.config.style.paddingB + 'px',
		paddingLeft: props.config.style.paddingL + 'px',
		borderTopLeftRadius: props.config.style.bgRTL + 'px',
		borderTopRightRadius: props.config.style.bgRTR + 'px',
		borderBottomLeftRadius: props.config.style.bgRBL + 'px',
		borderBottomRightRadius: props.config.style.bgRBR + 'px',
		boxShadow: `${props.config.style.shadowX}px ${props.config.style.shadowY}px ${props.config.style.shadowDegree}px ${props.config.style.shadowColor}`
	}))

	const titleStyle = computed(() => ({
		fontSize: props.config.style.titleSize + 'px',
		color: props.config.style.titleColor,
		fontWeight: props.config.style.titleWeight ? 'bold' : 'normal',
		fontStyle: props.config.style.titleStyle ? 'italic' : 'normal',
		textDecoration: props.config.style.titleLine ? 'underline' : 'none'
	}))

	const titleIconStyle = computed(() => ({
		fontSize: props.config.style.titleIconSize + 'px',
		color: props.config.style.titleIconColor,
		marginRight: '5px'
	}))

	const titleEndStyle = computed(() => ({
		fontSize: props.config.style.titleEndSize + 'px',
		color: props.config.style.titleEndColor,
		fontWeight: props.config.style.titleEndWeight ? 'bold' : 'normal',
		fontStyle: props.config.style.titleEndStyle ? 'italic' : 'normal',
		textDecoration: props.config.style.titleEndLine ? 'underline' : 'none'
	}))

	const titleEndIconStyle = computed(() => ({
		fontSize: props.config.style.titleEndIconSize + 'px',
		color: props.config.style.titleEndIconColor,
		marginLeft: '5px'
	}))
</script>

<style scoped lang="less">
	.container {
		height: 100%;
		width: 100%;
		display: flex;
		flex-direction: column;
	}

	.title-container {
		display: flex;
		align-items: center;
		margin-bottom: 10px;
	}

	.chart-container {
		flex: 1;
		width: 100%;
		min-height: 100px;
	}
</style>
